<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #canvas {
            background-color: #FFF;
        }

        body {
            background-color: #000;
            /*font-family: "Microsoft YaHei", sans-seri;*/
        }
    </style>
</head>
<body>
<canvas id="canvas" width="800" height="500"></canvas>
</body>
<script>
    let canvas = document.querySelector('#canvas');
    let ctx = canvas.getContext('2d');

    let [cx, cy, r] = [500, 300, 100];
    let arr = [
        {data: 300, bg: '#ff5700', txt: '数据1'},
        {data: 100, bg: '#ff97aa', txt: '数据2'},
        {data: 200, bg: '#cccccc', txt: '数据3'},
        {data: 300, bg: '#666666', txt: '数据4'},
        {data: 150, bg: '#588', txt: '数据5'},
        {data: 90, bg: '#a00', txt: '数据6'}
    ];

    function d2a(n) {
        return n * Math.PI / 180;
    }

    function pieData(start, end, item) {
        let fontsize = 14;
        let len = 20;
        let txt_len = item.txt.length * (fontsize + 2);    // 文字的宽度
        let arc = d2a(start) + (d2a(end ) - d2a(start)) / 2;  // 获取扇形中间的位置

        let obj  = {    // 扇形中间位置的x和y轴的坐标
            x : cx + Math.cos(arc) * r,
            y : cy + Math.sin(arc) * r,
        }

        if (obj.x <= cx) {    // 文字在饼图左边
            obj.x1 = obj.x - len;
            obj.txtX = obj.x1 - txt_len;
            obj.x2 = obj.x1 - 10;
        } else {       // 文字在饼图右边
            obj.x1 = obj.x + len;
            obj.txtX = obj.x1 + fontsize;
            obj.x2 = obj.x1 + 10;
        }

        if (obj.y <= cy) {     // 文字在饼图上边
            obj.y1 = obj.y - len;
            obj.txtY = obj.y1 + fontsize / 2;
        } else {      // 文字在饼图下边
            obj.y1 = obj.y + len;
            obj.txtY = obj.y1 + fontsize / 2;
        }

        ctx.beginPath();
        ctx.strokeStyle = item.bg;
        ctx.moveTo(obj.x, obj.y);
        ctx.lineTo(obj.x1, obj.y1);
        ctx.lineTo(obj.x2, obj.y1);
        ctx.stroke();

        ctx.font = fontsize + 'px 微软雅黑';
        ctx.fillText(item.txt, obj.txtX, obj.txtY);
        ctx.closePath();
    }

    function pie(start, end, item) {
        ctx.beginPath();
        ctx.fillStyle = item.bg;
        ctx.moveTo(cx, cy);
        ctx.arc(cx, cy, r, d2a(start), d2a(end), false);
        ctx.fill();
        ctx.closePath();
        pieData(start, end, item);
    }

    let max = 0;
    for (let i = 0, l = arr.length; i < l; i++) {
        max += arr[i].data;
    }

    let n = 0;
    arr.forEach((item) => {
        let arg = item.data / max * 360;
        pie(n, n + arg, item);
        n += arg;
    })

</script>
</html>